﻿using OneOfAll.Common.Models;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;

namespace OneOfAll.Common.Util
{
    /// <summary>
    /// 系统基本方法扩展类，相比系统自带更安全可靠
    /// </summary>
    public static class TypeExtension
    {
        private const int HEIGHT_CHINESE = 0x9fbb;
        private const int LOW_CHINESE = 0x4e00;

        public static void LogExceptions(this Task task, string title = "Task")
        {
            task.ContinueWith(t =>
            {
                var aggException = t.Exception.Flatten();
                foreach (var item in aggException.InnerExceptions)
                {
                    LogHelper.Instance.GetLog(LogTypeEnum.Error, title, item);
                }
            }, TaskContinuationOptions.OnlyOnFaulted);
        }

        /// <summary> 
        /// 获取结构体字段的说明文本
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="attribute">属性类型</param>
        /// <returns></returns>
        public static Attribute GetAttributrByField(this FieldInfo field, Type attribute)
        {
            var atrrs = field.GetCustomAttributes(false);
            foreach (Attribute item in atrrs)
            {
                if (item.GetType() == attribute)
                {
                    return item;
                }
            }
            return null;
        }
        /// <summary>
        /// 获取类属性的说明文本
        /// </summary>
        /// <param name="property"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public static Attribute GetAttributrByProperty(this PropertyInfo property, Type attribute)
        {
            var atrrs = property.GetCustomAttributes(false);
            foreach (Attribute item in atrrs)
            {
                if (item.GetType() == attribute)
                {
                    return item;
                }
            }
            return null;
        }
        
        public static T GetAttributeByProperty<T>(this PropertyInfo property) where T : Attribute
        {
            var atrrs = property.GetCustomAttributes(false);
            var targetType = typeof(T);
            foreach (Attribute item in atrrs)
            {
                if (item.GetType() == targetType)
                {
                    return item as T;
                }
            }
            return null;
        }

        public static bool IsEmpty(this string value)
        {
            return value == null || value == "";
        }

        /// <summary>
        /// 检查是否为非法字符
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static bool IsSpecialChar(this string Value)
        {
            return Regex.IsMatch(Value, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|\*|~|!|@|#|\||$|^|&|-|+|\=|\?|%|_|\\|>
                    |<|\.|\,|`|￥|……|、|。|，|》|《|？|：|;|；|‘|’|'|【|】|\“|\""|\”||]");
        }

        public static int ToInt32(this string str)
        {
            int res = 0;
            if (!string.IsNullOrEmpty(str))
            {
                int.TryParse(str, out res);
            }
            return res;
        }
        public static DateTime ToDate(this string value, string format)
        {
            DateTime date = DateTime.Now;
            try
            {
                date = DateTime.ParseExact(value, format, null);
            }
            catch
            {
            }
            return date;
        }
        public static bool IsEmpty<T>(this List<T> value)
        {
            return value == null || value.Count == 0;
        }
        public static void AddRange<T>(this ICollection<T> @this, IEnumerable<T> values)
        {
            foreach (T local in values)
            {
                @this.Add(local);
            }
        }

        public static string AllMessage(this Exception ex)
        {
            if (ex == null)
            {
                return string.Empty;
            }
            StringBuilder builder = new StringBuilder();
            builder.Append(ex.Message);
            if (ex.InnerException != null)
            {
                builder.Append(Environment.NewLine);
                builder.Append(">").Append(ex.InnerException.AllMessage());
            }
            return builder.ToString();
        }

        public static void Append(this Stream stream, Stream descSream)
        {
            byte[] buffer = new byte[descSream.Length];
            descSream.Read(buffer, 0, buffer.Length);
            descSream.Seek(0L, SeekOrigin.Begin);
            stream.Write(buffer, 0, buffer.Length);
        }


        public static void AppendKeyValue(this StringBuilder builder, string key, object value, string end = " ")
        {
            if ((value != null) && !value.ToString().IsInvalid())
            {
                builder.AppendFormat("{0}：{1}{2}", key, value, end);
            }
        }


        public static void AppendKeyValueNewLine(this StringBuilder sb, string key, object value)
        {
            if ((value != null) && !value.ToString().IsInvalid())
            {
                sb.Append(key).Append("：").Append(value).Append(Environment.NewLine);
            }
        }

        public static bool Contains(this string value, string match, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase) =>
            (value.IndexOf(match, comparison) > -1);

        public static IEnumerable<Ttarget> ConvertAll<Ttarget>(this IEnumerable @this) where Ttarget : class
        {
            if (@this == null)
            {
                return null;
            }
            IEnumerable<Ttarget> enumerable = @this as IEnumerable<Ttarget>;
            if (enumerable != null)
            {
                return enumerable;
            }
            Collection<Ttarget> collection = new Collection<Ttarget>();
            foreach (object obj2 in @this)
            {
                Ttarget item = obj2 as Ttarget;
                if (item == null)
                {
                    throw new ArgumentException("invalid Target:" + typeof(Ttarget));
                }
                collection.Add(item);
            }
            return collection;
        }

        public static IEnumerable<Ttarget> ConvertAllyield<Ttarget>(this IEnumerable @this) where Ttarget : class
        {
            if (@this != null)
            {
                IEnumerator enumerator = @this.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    object current = enumerator.Current;
                    Ttarget iteratorVariable1 = current as Ttarget;
                    yield return iteratorVariable1;
                }
            }
        }

        /// <summary>
        /// 深拷贝数据 - 拷贝自身 - 支持IList，IDictionary和Model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T CopyNoSerialization<T>(this T obj) where T : class, new()
        {
            try
            {
                if (obj == null)
                    return default(T);
                T t;
                if (IsNewctor(obj.GetType()))
                    t = Activator.CreateInstance(obj.GetType()) as T;
                else
                    t = new T();
                return obj.CopyTo(t);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return obj as T;
            }
        }

        public static bool IsNewctor(Type type)
        {
            if (type.IsValueType)
                return true;
            if (type.GetConstructors().Length == 0)
                return true;
            return type.GetConstructors().Any(x => x.IsConstructor && x.GetParameters().Length == 0);
        }

        /// <summary>
        /// 深拷贝数据 - 支持IList，IDictionary和Model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T CopyTo<T>(this object obj, T t) where T : class, new()
        {
            try
            {
                if (t == null)
                    return default(T);
                if (obj == null)
                    return default(T);
                var type = t.GetType();
                var objType = obj.GetType();
                if (type.IsValueType)
                {
                    return t = (T)obj;
                }
                if (type.GetInterfaces().Contains(typeof(IList)))
                {
                    IList newList = (IList)Activator.CreateInstance(type);
                    var types = type.GetGenericArguments();
                    foreach (var itemObj in (IList)obj)
                    {
                        if (IsNewctor(types.First().GetType()))
                            newList.Add(itemObj.CopyTo(Activator.CreateInstance(types.First())));
                        else
                            newList.Add(itemObj.Copy());
                    }
                    return newList as T;
                }
                if (type.GetInterfaces().Contains(typeof(IDictionary)))
                {
                    IDictionary newDic = (IDictionary)Activator.CreateInstance(type);
                    var modelDic = (IDictionary)obj;
                    foreach (var itemkey in modelDic.Keys)
                    {
                        newDic.Add(itemkey.Copy(), modelDic[itemkey].Copy());
                    }
                    return newDic as T;
                }
                foreach (var item in objType.GetProperties())
                {
                    if (!item.CanRead)
                        continue;
                    var proper = type.GetProperty(item.Name);
                    if (proper == null)
                        continue;
                    if (!proper.CanWrite)
                        continue;
                    if (proper.PropertyType.IsValueType || proper.PropertyType == typeof(string))
                        proper.SetValue(t, item.GetValue(obj));
                    else
                        proper.SetValue(t, item.GetValue(obj).Copy());
                }
                return t;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return default(T);
            }
        }

        public static T Copy<T>(this T obj) where T : class
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                formatter.Serialize(stream, obj);
                stream.Seek(0L, SeekOrigin.Begin);
                T local = default(T);
                try
                {
                    local = (T)formatter.Deserialize(stream);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return local;
            }
        }

        private static object Copy1(this object obj)
        {
            Type type = obj.GetType();
            if (type.IsValueType)
            {
                return obj;
            }
            object obj2 = Activator.CreateInstance(type);
            MemberInfo[] members = obj.GetType().GetMembers();
            foreach (MemberInfo info in members)
            {
                if (info.MemberType == MemberTypes.Field)
                {
                    FieldInfo info2 = (FieldInfo)info;
                    object obj3 = info2.GetValue(obj);
                    if (obj3 is ICloneable)
                    {
                        info2.SetValue(obj2, (obj3 as ICloneable).Clone());
                    }
                    else
                    {
                        info2.SetValue(obj2, obj3.Copy<object>());
                    }
                }
                else if (info.MemberType == MemberTypes.Property)
                {
                    PropertyInfo info3 = (PropertyInfo)info;
                    if (info3.GetSetMethod(false) != null)
                    {
                        object obj4 = info3.GetValue(obj, null);
                        if (obj4 is ICloneable)
                        {
                            info3.SetValue(obj2, (obj4 as ICloneable).Clone(), null);
                        }
                        else
                        {
                            info3.SetValue(obj2, obj4.Copy<object>(), null);
                        }
                    }
                }
            }
            return obj2;
        }

        public static object CreateInstance(this Type @this)
        {
            try
            {
                return Activator.CreateInstance(@this);
            }
            catch
            {
                return null;
            }
        }


        public static T FindFirst<T>(this IEnumerable<T> source) where T : class
        {
            if (!source.IsInvalid<T>())
            {
                using (IEnumerator<T> enumerator = source.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        return enumerator.Current;
                    }
                }
            }
            return default(T);
        }

        public static object FindFirst(this IEnumerable source)
        {
            if (!source.IsInvalid())
            {
                IEnumerator enumerator = source.GetEnumerator();

                while (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }
            }
            return null;
        }

        public static void ForEach<T>(this IEnumerable<T> souce, Action<T> action)
        {
            if (!souce.IsInvalid<T>())
            {
                foreach (T local in souce)
                {
                    action(local);
                }
            }
        }

        public static string Format(this string @this, object arg0) =>
            string.Format(@this, arg0);

        public static string Format(this string @this, params object[] arg0) =>
            string.Format(@this, arg0);

        public static string Format(this string @this, object arg0, object arg1) =>
            string.Format(@this, arg0, arg1);

        public static string Format(this string @this, object arg0, object arg1, object arg2) =>
            string.Format(@this, arg0, arg1, arg2);

        /// <summary>
        /// 获取属性字符串名称
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr"></param>
        /// <returns></returns>
        public static string GetPropertyName<T>(this Expression<Func<T, object>> expr) =>
            ((MemberExpression)expr.Body).Member.Name;

        public static TEnum GetSafeAttributeEnum<TEnum>(this XmlNode node, string attribute, TEnum defaultValue)
        {
            try
            {
                string safeAttributeValue = node.GetSafeAttributeValue(attribute);
                if (safeAttributeValue.IsValid())
                {
                    return safeAttributeValue.Replace("，", ",").ToEnum<TEnum>();
                }
            }
            catch
            {
            }
            return defaultValue;
        }

        public static string GetSafeAttributeValue(this XmlNode node, string attribute)
        {
            if ((node != null) && (node.Attributes != null))
            {
                XmlAttribute attribute2 = node.Attributes[attribute];
                return attribute2?.Value.Trim();
            }
            return string.Empty;
        }

        public static TValue GetSafeValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defalut)
        {
            if (!dictionary.IsInvalid<KeyValuePair<TKey, TValue>>() && dictionary.ContainsKey(key))
            {
                return dictionary[key];
            }
            return defalut;
        }

        public static T GetSafeValue<T>(this IList<T> @this, int index, T defaultValue)
        {
            if (@this.IsInvalid<T>())
            {
                return defaultValue;
            }
            if (@this.Count > index)
            {
                return defaultValue;
            }
            return @this[index];
        }

        public static string GetString(this byte[] bytes) =>
            bytes.GetString(Encoding.Default);

        public static string GetString(this byte[] bytes, Encoding encode)
        {
            if ((bytes == null) || (bytes.Count<byte>() <= 0))
            {
                return string.Empty;
            }
            return encode.GetString(bytes);
        }


        public static bool IsBetween<T>(this T @this, T lower, T upper, bool includeLower = true, bool includeUpper = true) where T : IComparable<T>
        {
            if (@this == null)
            {
                return false;
            }
            int num = @this.CompareTo(lower);
            int num2 = @this.CompareTo(upper);
            return (((includeLower && (num == 0)) || (includeUpper && (num2 == 0))) || ((num > 0) && (num2 < 0)));
        }

        public static bool IsBetween<T>(this T @this, T lower, T upper, IComparer<T> comparer, bool includeLower = true, bool includeUpper = true)
        {
            if (@this == null)
            {
                return false;
            }
            int num = comparer.Compare(@this, lower);
            int num2 = comparer.Compare(@this, upper);
            return (((includeLower && (num == 0)) || (includeUpper && (num2 == 0))) || ((num > 0) && (num2 < 0)));
        }

        public static bool IsChinese(this char value) =>
            ((value >= '一') && (value <= 0x9fbb));

        public static bool IsCompatibleType(this Type type1, Type type2)
        {
            if (type1 == type2)
            {
                return true;
            }
            if (type1.IsEnum && (Enum.GetUnderlyingType(type1) == type2))
            {
                return true;
            }
            Type underlyingType = Nullable.GetUnderlyingType(type1);
            Type type3 = Nullable.GetUnderlyingType(type2);
            return (((underlyingType != null) && (type3 != null)) && underlyingType.IsCompatibleType(type3));
        }

        public static bool IsGreaterThanZero(this int value) =>
            (value > 0);

        public static bool IsGreaterThanZero(this int? value)
        {
            if (!value.HasValue)
            {
                return false;
            }
            return (value > 0);
        }

        public static bool IsHasChinese(this string value) =>
            value.Any<char>(c => c.IsChinese());

        public static bool IsImplementsInterface(this Type objectType, Type interfaceType)
        {
            if (!interfaceType.IsInterface)
            {
                throw new ArgumentException($"查找类似 指定的类型{interfaceType.Name}不是接口类型。", "interfaceType");
            }
            foreach (Type type in objectType.GetInterfaces())
            {
                if (type == interfaceType)
                {
                    return true;
                }
                if (type.Name.Contains("`") && ((type.Name == interfaceType.Name) && (type.Assembly == interfaceType.Assembly)))
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsInstanceOfT<T>(this object instance)
        {
            if (instance == null)
            {
                return false;
            }
            return instance.GetType().IsInstanceOfType(typeof(T));
        }

        public static bool IsInstanceOfT<T>(this Type instanceType) =>
            instanceType.IsInstanceOfType(typeof(T));

        public static bool IsInstanceOfType(this object instance, Type type)
        {
            if (instance == null)
            {
                return false;
            }
            return instance.GetType().IsInstanceOfType(type);
        }


        public static bool IsInvalid<T>(this IEnumerable<T> source) =>
            !source.IsValid<T>();

        public static bool IsInvalid(this IEnumerable @this) =>
            !@this.IsValid();

        public static bool IsInvalid(this string value) =>
            value.IsNullOrEmptyOrWhiteSpace();

        public static bool IsMatch(this string source, string pattern)
        {
            if (source.IsInvalid())
            {
                return false;
            }
            return source.IsMatch(pattern, (RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase));
        }

        public static bool IsMatch(this string source, string pattern, RegexOptions options)
        {
            if (source.IsInvalid())
            {
                return false;
            }
            return Regex.IsMatch(source, pattern, options);
        }


        public static bool IsNullOrEmpty(this string value) =>
            string.IsNullOrEmpty(value);

        public static bool IsNullOrEmptyOrWhiteSpace(this string value)
        {
            bool flag = value.IsNullOrEmpty();
            if (!flag)
            {
                flag = value.Trim().IsNullOrEmpty();
            }
            return flag;
        }

        public static bool IsValid<T>(this IEnumerable<T> source) =>
            ((source != null) && source.Any<T>());

        public static bool IsValid(this IEnumerable @this)
        {
            if (@this != null)
            {
                foreach (object obj2 in @this)
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsValid(this DateTime value)
        {
            if ((DateTime.MinValue == value) || (DateTime.MaxValue == value))
            {
                return false;
            }
            return true;
        }

        public static bool IsValid(this DateTime? value)
        {
            DateTime minValue = DateTime.MinValue;
            DateTime? nullable = null;
            if (value.HasValue)
            {
                minValue = DateTime.MinValue;
                nullable = value;
            }
            if ((nullable.HasValue && (minValue == nullable.GetValueOrDefault()))
                || ((nullable = value).HasValue && ((minValue = DateTime.MaxValue) == nullable.GetValueOrDefault())))
            {
                return false;
            }
            return true;
        }

        public static bool IsValid(this string value) =>
            !value.IsNullOrEmptyOrWhiteSpace();

        public static bool IsValid(this Version value) =>
            ((((value?.Major > 0) || (value.Minor > 0)) || (value.Build > 0)) || (value.Revision > 0));

        public static System.Text.RegularExpressions.Match Match(this string source, string pattern) =>
            source.Match(pattern, (RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase));

        public static System.Text.RegularExpressions.Match Match(this string source, string pattern, RegexOptions options) =>
            Regex.Match(source, pattern, options);


        public static T SafeValue<T>(this T? @this) where T : struct
        {
            T? nullable = @this;
            return (nullable.HasValue ? nullable.GetValueOrDefault() : default(T));
        }

        public static string To16Bland(this byte value) =>
            value.ToString("X2");

        public static string To16Bland(this byte[] values, string separator = " ")
        {
            if ((values == null) || (values.Length <= 0))
            {
                return string.Empty;
            }
            StringBuilder builder = new StringBuilder();
            foreach (byte num in values)
            {
                builder.Append(num.To16Bland()).Append(separator);
            }
            return builder.ToString();
        }

        public static byte[] ToASCIIBytes(this string value) =>
            value.ToBytes(Encoding.ASCII);

        public static string ToBinary(this byte value) =>
            Convert.ToString(value, 2);

        public static string ToBinary(this byte[] values, string separator = " ")
        {
            if ((values == null) || (values.Length <= 0))
            {
                return string.Empty;
            }
            StringBuilder builder = new StringBuilder();
            foreach (byte num in values)
            {
                builder.Append(num.ToBinary()).Append(separator);
            }
            return builder.ToString();
        }

        public static bool ToBoolean(this string value)
        {
            bool flag;
            if (!bool.TryParse(value, out flag))
            {
                throw new InvalidCastException("\"" + value + "\"不是有效的boolean，请确认。");
            }
            return flag;
        }

        public static byte ToByte(this int value)
        {
            try
            {
                return BitConverter.GetBytes(value)[0];
            }
            catch
            {
                return 0;
            }
        }

        public static byte[] ToBytes(this string value) =>
            value.ToBytes(Encoding.Default);

        public static byte[] ToBytes(this string value, Encoding encode) =>
            encode.GetBytes(value);

        public static string ToCNString(this bool value) =>
            (value ? "是" : "否");

        public static string ToCNString(this bool? value) =>
            (value.HasValue ? value.ToString() : string.Empty);

        public static string ToDateString(this DateTime value) =>
            (value.IsValid() ? value.ToString("yyyy-MM-dd") : string.Empty);

        public static string ToDateString(this DateTime? value)
        {
            if (value.HasValue)
            {
                return (value.IsValid() ? value.Value.ToString("yyyy-MM-dd") : string.Empty);
            }
            return string.Empty;
        }

        public static string ToDateString(this DateTime? value, string format, string defaultStr = "")
        {
            if (value.HasValue)
            {
                return (value.IsValid() ? value.Value.ToString(format) : defaultStr);
            }
            return defaultStr;
        }

        public static string ToDateStringFromNow(this DateTime dt)
        {
            if (!dt.IsValid())
            {
                return string.Empty;
            }
            TimeSpan span = (TimeSpan)(DateTime.Now - dt);
            if (span.TotalDays > 365.0)
            {
                return $"{((int)Math.Floor((double)(span.TotalDays / 365.0)))}年前";
            }
            if (span.TotalDays > 30.0)
            {
                return $"{((int)Math.Floor((double)(span.TotalDays / 30.0)))}个月前";
            }
            if (span.TotalDays > 7.0)
            {
                return $"{((int)Math.Floor((double)(span.TotalDays / 7.0)))}周前";
            }
            if (span.TotalDays > 1.0)
            {
                return $"{((int)Math.Floor(span.TotalDays))}天前";
            }
            if (span.TotalHours > 1.0)
            {
                return $"{((int)Math.Floor(span.TotalHours))}小时前";
            }
            if (span.TotalMinutes > 1.0)
            {
                return $"{((int)Math.Floor(span.TotalMinutes))}分钟前";
            }
            if (span.TotalSeconds >= 1.0)
            {
                return $"{((int)Math.Floor(span.TotalSeconds))}秒前";
            }
            if (dt.Date == DateTime.Now.Date)
            {
                return "今天";
            }
            span = (TimeSpan)(dt - DateTime.Now);
            int num = (int)Math.Floor(Math.Abs(span.TotalDays));
            switch (num)
            {
                case 1:
                    return "明天";

                case 2:
                    return "后天";
            }
            if (num < 7)
            {
                return $"{num}天后";
            }
            if (num < 30)
            {
                return $"{(num / 7)}周后";
            }
            if (num < 0x16d)
            {
                return $"{(num / 30)}月后";
            }
            return $"{(num / 0x16d)}年后";
        }

        public static string ToDateStringFromNow(this DateTime? dt)
        {
            if (dt.HasValue)
            {
                return dt.Value.ToDateStringFromNow();
            }
            return string.Empty;
        }

        public static DateTime ToDateTime(this string dateTime)
        {
            DateTime time;
            if (!DateTime.TryParse(dateTime, out time))
            {
                throw new InvalidCastException("\"" + dateTime + "\"不是有效的时间格式，请确认。");
            }
            return time;
        }

        public static DateTime ToDateTime(this string value, string format, string culture = "zh-CHS")
        {
            DateTime time;
            if (!DateTime.TryParseExact(value, format, new CultureInfo("zh-CHS"), DateTimeStyles.None, out time))
            {
                throw new Exception($"字符串（{value}）不能按照格式（{format}）解析为日期时间");
            }
            return time;
        }

        public static string ToDateTimeString(this DateTime value)
        {
            if (!value.IsValid())
            {
                return string.Empty;
            }
            if (((value.Hour == 0) && (value.Minute == 0)) && (value.Second == 0))
            {
                return value.ToDateString();
            }
            return value.ToString("yyyy-MM-dd HH:mm:ss");
        }

        public static string ToDateTimeString(this DateTime? value)
        {
            if (value.IsValid())
            {
                return value.Value.ToDateTimeString();
            }
            return string.Empty;
        }

        public static decimal ToDecimal(this string value)
        {
            decimal num;
            if (!decimal.TryParse(value, out num))
            {
                throw new InvalidCastException("不能将字符串\"" + value + "\"转换为Decimal数字。");
            }
            return num;
        }

        //public static Dictionary<string, string> ToDictionaryH(this HttpContext context)
        //{
        //    if ((context == null) || (context.Request == null))
        //    {
        //        return new Dictionary<string, string>();
        //    }
        //    string httpMethod = context.Request.HttpMethod;
        //    NameValueCollection form = new NameValueCollection();
        //    if (httpMethod.Equals(EnumHttpMode.Post.GetDescription()))
        //    {
        //        form = context.Request.Form;
        //    }
        //    else if (httpMethod.Equals(EnumHttpMode.Get.GetDescription()))
        //    {
        //        form = context.Request.QueryString;
        //    }
        //    Dictionary<string, string> dictionary = new Dictionary<string, string>();
        //    if ((form != null) && (form.Count > 0))
        //    {
        //        foreach (string str2 in form)
        //        {
        //            dictionary.Add(str2, form[str2]);
        //        }
        //    }
        //    return dictionary;
        //}

        public static double ToDouble(this string value)
        {
            if (value.IsEmpty()) return 0;
            double num;
            double.TryParse(value, out num);
            return num;
        }

        public static float Tofloat(this string value)
        {
            if (value.IsEmpty()) return 0;
            float num;
            float.TryParse(value, out num);
            return num;
        }
        public static object GetValue(this PropertyInfo pi, object obj)
        {
            if ((pi == null) || (obj == null))
            {
                return null;
            }
            return pi.GetGetMethod()?.Invoke(obj, null);
        }
        public static List<object> ToDynamicCollection(this DataTable dt)
        {
            if (((dt == null) || (dt.Rows.Count <= 0)) || (dt.Columns.Count <= 0))
            {
                return new List<object>();
            }
            List<object> list = new List<object>();
            foreach (DataRow row in dt.Rows)
            {
                object obj2 = new ExpandoObject();
                foreach (DataColumn column in dt.Columns)
                {
                    ((IDictionary<string, object>)obj2)[column.ColumnName] = row[column];
                    list.Add((dynamic)obj2);
                }
            }
            return list;
        }

        public static T ToEnum<T>(this int value) =>
            value.ToString().ToEnum<T>();

        public static T ToEnum<T>(this string name)
        {
            Type type = typeof(T);
            if (!type.IsEnum)
            {
                throw new InvalidCastException("必须是枚举类型才能转换。");
            }
            return (T)Enum.Parse(typeof(T), name, true);
        }



        public static List<T> ToList<T>(this IEnumerator<T> source)
        {
            List<T> list = new List<T>();
            if (source != null)
            {
                while (source.MoveNext())
                {
                    list.Add(source.Current);
                }
            }
            return list;
        }

        public static string ToLogString(this Exception ex)
        {
            if (ex == null)
            {
                return string.Empty;
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("  >>异常消息（Message）：").AppendLine(ex.Message);
            builder.Append("  >>异常来源（Source）：").AppendLine(ex.Source);
            builder.Append("  >>异常类型（ExceptionType）：").AppendLine(ex.GetType().ToString());
            builder.Append("  >>原生异常类型（BaseExceptionType）：").AppendLine(ex.GetBaseException().GetType().ToString());
            builder.Append("  >>出错的方法签名（TargetSite）：").Append(ex.TargetSite);
            if (ex.Data.Count > 0)
            {
                builder.Append(Environment.NewLine);
                builder.Append("  >>自定义数据（Data）：");
                StringBuilder builder2 = new StringBuilder();
                foreach (DictionaryEntry entry in ex.Data)
                {
                    builder2.Append(string.Concat(new object[] { "Key：", entry.Key, "，Value：", entry.Value, "; " }));
                }
                builder.Append(builder2);
            }
            if (!string.IsNullOrEmpty(ex.StackTrace))
            {
                builder.Append(Environment.NewLine);
                builder.Append("  >>堆栈信息（StackTrace）：");
                builder.Append(Environment.NewLine);
                builder.Append(ex.StackTrace);
            }
            if (ex.InnerException != null)
            {
                builder.Append(Environment.NewLine);
                builder.Append(">>========================== 内部异常（InnerException）==========================");
                builder.Append(Environment.NewLine);
                builder.Append(ex.InnerException.ToLogString());
            }
            return builder.ToString();
        }

        public static string ToReverse(this string obj)
        {
            char[] array = obj.ToCharArray();
            Array.Reverse(array);
            return new string(array);
        }

        public static bool ToSafeBoolean(this string value, bool defaultValue = false)
        {
            bool flag;
            if (bool.TryParse(value, out flag))
            {
                return flag;
            }
            return defaultValue;
        }

        public static byte ToSafeByte(this string value)
        {
            byte num;
            if (byte.TryParse(value, out num))
            {
                return num;
            }
            return 0;
        }

        public static DateTime? ToSafeDateTime(this string dateTime)
        {
            DateTime time;
            if (DateTime.TryParse(dateTime, out time))
            {
                return new DateTime?(time);
            }
            return null;
        }

        public static decimal ToSafeDecimal(this string value)
        {
            decimal num;
            if (decimal.TryParse(value, out num))
            {
                return num;
            }
            return 0M;
        }

        public static double ToSafeDouble(this string value)
        {
            double num;
            if (double.TryParse(value, out num))
            {
                return num;
            }
            return 0.0;
        }

        public static T ToSafeEnum<T>(this string value, T defaultValue)
        {
            try
            {
                return value.ToEnum<T>();
            }
            catch
            {
                return defaultValue;
            }
        }

        public static int ToSafeInt(this string value)
        {
            int num;
            if (value.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator))
            {
                return (int)value.ToSafeDouble();
            }
            if (int.TryParse(value, out num))
            {
                return num;
            }
            return 0;
        }

        public static short ToSafeInt16(this string value)
        {
            short num;
            if (short.TryParse(value, out num))
            {
                return num;
            }
            return 0;
        }

        public static long ToSafeInt64(this string value)
        {
            long num;
            if (value.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator))
            {
                return (long)value.ToSafeDouble();
            }
            if (long.TryParse(value, out num))
            {
                return num;
            }
            return 0L;
        }

        public static string ToSafeString(this object obj) =>
            obj?.ToString();

        public static ulong ToSafeUlong(this string value)
        {
            if (!string.IsNullOrWhiteSpace(value))
            {
                ulong num;
                if (value.Contains(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator))
                {
                    return (ulong)value.ToSafeDouble();
                }
                if (ulong.TryParse(value, out num))
                {
                    return num;
                }
            }
            return 0L;
        }

        public static Version ToSafeVersion(this string value)
        {
            Version result = new Version();
            if (value.IsInvalid())
            {
                return result;
            }
            if (Version.TryParse(value, out result))
            {
                return result;
            }
            MatchCollection matchs = Regex.Matches(value, @"(\d{1,8}\.){1,3}\d{1,8}", RegexOptions.IgnoreCase);
            if (matchs.Count == 0)
            {
                return result;
            }
            return matchs[0].ToSafeString().ToSafeVersion();
        }

        public static string ToShortString(this Version value)
        {
            if (!value.IsValid())
            {
                return string.Empty;
            }
            if (((value.Minor <= 0) && (value.Build <= 0)) && (value.Revision <= 0))
            {
                return $"{value.Major}";
            }
            if ((value.Build <= 0) && (value.Revision <= 0))
            {
                return $"{value.Major}.{value.Minor}";
            }
            if (value.Revision <= 0)
            {
                return $"{value.Major}.{value.Minor}.{value.Build}";
            }
            return $"{value.Major}.{value.Minor}.{value.Build}.{value.Revision}";
        }

        public static DateTime? ToUTCTime(this string dateTime)
        {
            DateTime? nullable = dateTime.ToSafeDateTime();
            if (nullable.HasValue)
            {
                return nullable;
            }
            Regex regex = new Regex(@"(?i)\d+ [a-z]+ \d{4} \d+:\d+:\d+ [-\+]\d+");
            return regex.Match(dateTime).Value.ToSafeDateTime();
        }


        public static string TrimEnd(this string value, string end, StringComparison comparison = StringComparison.Ordinal)
        {
            if (value.IsInvalid())
            {
                return value;
            }
            if (end.IsInvalid())
            {
                return value.TrimEnd(new char[0]);
            }
            if (!value.EndsWith(end, comparison))
            {
                return value;
            }
            int length = value.LastIndexOf(end, comparison);
            return value.Substring(0, length);
        }

        public static string TrimStart(this string value, string star)
        {
            if (star.IsInvalid())
            {
                return value.TrimStart(new char[0]);
            }
            if (!value.StartsWith(star))
            {
                return value;
            }
            return value.Substring(star.Length);
        }

        //public static string UrlDecode(this string source, EnumEncodingType encodingType)
        //{
        //    if (!string.IsNullOrEmpty(source))
        //    {
        //        Encoding e = Encoding.GetEncoding(encodingType.GetDescription());
        //        return HttpUtility.UrlDecode(source, e);
        //    }
        //    return string.Empty;
        //}

        //public static string UrlEncode(this string source, EnumEncodingType encodingType)
        //{
        //    if (!string.IsNullOrEmpty(source))
        //    {
        //        Encoding e = Encoding.GetEncoding(encodingType.GetDescription());
        //        return HttpUtility.UrlEncode(source, e);
        //    }
        //    return string.Empty;
        //}

        public static IQueryable<T> WhereIf<T>(this IQueryable<T> @this, Expression<Func<T, bool>> predicate, bool condition) =>
            (condition ? @this.Where<T>(predicate) : @this);

        /// <summary>
        /// 按条数对数组分组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="parts"></param>
        /// <returns></returns>
        public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
        {
            return list.Select((item, index) => new { index, item })
                       .GroupBy(x => x.index / parts)
                       .Select(x => x.Select(y => y.item));
        }
        /// <summary>
        /// 字典添加
        /// </summary>
        /// <param name="list"></param>
        /// <param name="key"></param>
        public static void DictionaryAdd(this Dictionary<string, int> list, string key)
        {
            if (list.ContainsKey(key))
            {
                list[key]++;
            }
            else
            {
                list.Add(key, 1);
            }
        }
    }
}

